package com.sws.orderMS.command;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import com.sws.orderMS.command.impl.ListMyOrderCommand;
import com.sws.orderMS.command.impl.ListProductCommand;
import com.sws.orderMS.command.impl.ModifyCommand;
import com.sws.orderMS.command.impl.OrderCommand;
import com.sws.orderMS.command.impl.OrderManageCommand;
import com.sws.orderMS.command.impl.PayCommand;
import com.sws.orderMS.command.impl.ProductManageCommand;
import com.sws.orderMS.command.impl.RechargeCommand;
import com.sws.orderMS.command.impl.UserManageCommand;
import com.sws.orderMS.pojo.Client;
import com.sws.orderMS.pojo.Manager;
import com.sws.orderMS.pojo.User;
import com.sws.orderMS.tool.Tool;

public class UserCommandFactory extends CommandFactory {

	private User user;
	private static Map<CommandCode, Class<? extends Command>> ManagerCommandMap = 
			new HashMap<>();
	private static Map<CommandCode, Class<? extends Command>> ClientCommandMap = 
			new HashMap<>();
	static {
		ClientCommandMap.put(CommandCode.LIST_PRODUCT, ListProductCommand.class);
		ClientCommandMap.put(CommandCode.LIST_MY_ORDER, ListMyOrderCommand.class);
		ClientCommandMap.put(CommandCode.MODIFY, ModifyCommand.class);
		ClientCommandMap.put(CommandCode.ORDER, OrderCommand.class);
		ClientCommandMap.put(CommandCode.PAY, PayCommand.class);
		ClientCommandMap.put(CommandCode.RECHARGE, RechargeCommand.class);
		
		ManagerCommandMap.put(CommandCode.USER_MANAGE, UserManageCommand.class);
		ManagerCommandMap.put(CommandCode.PRODUCT_MANAGE, ProductManageCommand.class);
		ManagerCommandMap.put(CommandCode.ORDER_MANAGE, OrderManageCommand.class);
	}
	
	public UserCommandFactory(User user) {
		this.user = user;
	}
	
	@Override
	public Command buildCommand(CommandCode cmd) {
		if (user instanceof Manager) {
			ManagerCommandFactory factory = this.new ManagerCommandFactory();
			return factory.buildCommand(cmd);
		} else if (user instanceof Client) {
			ClientCommandFactory factory = this.new ClientCommandFactory();
			return factory.buildCommand(cmd);
		}
		return null;
	}

	class ManagerCommandFactory extends SystemCommandFactory {
		private Manager manager;
		
		public ManagerCommandFactory() {
			this.manager = (Manager)user;
		}
		
		public Command buildCommand(CommandCode cmd) {
			
			Class<? extends Command> clazz = ManagerCommandMap.get(cmd);
			
			if (clazz == null) {
				return super.buildCommand(cmd);
			}
			try {
				Constructor<? extends Command> c = clazz.getConstructor(User.class);
				Command command = c.newInstance(manager);
				return command;
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			return null;
		}
	}
	
	class ClientCommandFactory extends SystemCommandFactory {
		private Client client;
		
		public ClientCommandFactory() {
			this.client = (Client)user;
		}
		
		public Command buildCommand(CommandCode cmd) {
			Class<? extends Command> clazz = ClientCommandMap.get(cmd);
			
			if (clazz == null) {
				return super.buildCommand(cmd);
			}
			try {
				Constructor<? extends Command> c = clazz.getConstructor(User.class);
				Command command = c.newInstance(client);
				return command;
			} catch (NoSuchMethodException e) {
				e.printStackTrace();
			} catch (SecurityException e) {
				e.printStackTrace();
			} catch (InstantiationException e) {
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			} catch (IllegalArgumentException e) {
				e.printStackTrace();
			} catch (InvocationTargetException e) {
				e.printStackTrace();
			}
			return null;
		}
	}
	
}
